package com.htht.common.service;

import java.io.Serializable;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
/**
 * 支持不同数据库用户配置
 *
 */
public class SessionManager {

    /**
	 * Location of hibernate.cfg.xml file. Location should be on the classpath
	 * as Hibernate uses #resourceAsStream style lookup for its configuration
	 * file. The default classpath location of the hibernate config file is in
	 * the default package. Use #setConfigFile() to update the location of the
	 * configuration file for the current session.
	 */
//	private String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
	private final ThreadLocal<Session> sessionThreadLocal = new ThreadLocal<Session>();
	private final ThreadLocal<Transaction> transactionThreadLocal = new ThreadLocal<Transaction>();
	private Configuration configuration = new Configuration();
	private SessionFactory sessionFactory;
	private String configFile = "";
	private Logger logger = Logger.getLogger(HibernateSessionFactory.class);
	
//	static
//	{
//		try
//		{
//			configuration.configure(configFile);
//			sessionFactory = configuration.buildSessionFactory();
//		}
//		catch (HibernateException e)
//		{
//			logger.error(e.toString());
//			throw new HibernateException(e);
//		}
//	}
	
	/**
	 * 带参构�?
	 * @param hbmPath 配置文件路径
	 */
	public SessionManager(String hbmPath)
	{
		configFile = hbmPath;
		try
		{
			configuration.configure(configFile);
			sessionFactory = configuration.buildSessionFactory();
		}
		catch (HibernateException e)
		{
			logger.error(e.toString());
			throw new HibernateException(e);
		}
	}
	
	
	
	public SessionFactory getSessionFactory()
	{
		return sessionFactory;
	}
	
	public void rebuildSessionFactory()
	{
		synchronized (sessionFactory)
		{
			try
			{
				configuration.configure(configFile);
				sessionFactory = configuration.buildSessionFactory();
			}
			catch (HibernateException e)
			{
				logger.error(e.toString());
				throw new HibernateException(e);
			}
		}
	}
	
	public Session getSession()
	{
		Session session = (Session) sessionThreadLocal.get();
		
		try
		{
			if (session == null || !session.isOpen())
			{
				if (sessionFactory == null)
				{
					rebuildSessionFactory();
				}
				
				session = (sessionFactory != null) ? sessionFactory.openSession() : null;
				sessionThreadLocal.set(session);
			}
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSession FactoryopenSession");
			throw new HibernateException(e);
		}
		
		return session;
	}
	
	public void closeSession()
	{
		Session session = (Session) sessionThreadLocal.get();
		sessionThreadLocal.set(null);
		try
		{
			if (session != null && session.isOpen())
			{
				session.close();
			}
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSessionFactory close");
			throw new HibernateException(e);
		}
	}
	
	public void beginTransaction()
	{
		Transaction transaction = (Transaction) transactionThreadLocal.get();
		try
		{
			if (transaction == null)
			{
				transaction = getSession().beginTransaction();
				transactionThreadLocal.set(transaction);
			}
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSessionFactory beginTransaction");
			throw new HibernateException(e);
		}
	}
	
	public void commitTransaction()
	{
		Transaction transaction = (Transaction) transactionThreadLocal.get();
		
		try
		{
			if (transaction != null && !transaction.wasCommitted() && !transaction.wasRolledBack())
			{
				transaction.commit();
			}
			transactionThreadLocal.set(null);
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSessionFactory commitTransaction");
			throw new HibernateException(e);
		}
	}
	
	public void rollbackTransaction()
	{
		Transaction transaction = (Transaction) transactionThreadLocal.get();
		try
		{
			transactionThreadLocal.set(null);
			if (transaction != null && !transaction.wasCommitted() && !transaction.wasRolledBack())
			{
				transaction.rollback();
			}
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSessionFactory rollbackTransaction");
			throw new HibernateException(e);
		}
		finally
		{
			closeSession();
		}
	}
	
	public void setConfigFile(String configFile)
	{
//		SessionManager.configFile = configFile;
//		sessionFactory = null;
	}
	
	public Configuration getConfiguration()
	{
		return configuration;
	}
	
	public void add(Object entity)
	{
		try
		{
			beginTransaction();
			getSession().save(entity);
			commitTransaction();
			rollbackTransaction();
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSessionFactory add");
			throw new HibernateException(e);
		}
	}
	
	public void update(Object entity)
	{
		try
		{
			beginTransaction();
			getSession().update(entity);
			commitTransaction();
			rollbackTransaction();
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSessionFactory update");
			throw new HibernateException(e);
		}
	}
	
	public void delete(Object entity)
	{
		try
		{
			beginTransaction();
			getSession().delete(entity);
			commitTransaction();
			rollbackTransaction();
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSessionFactory delete");
			throw new HibernateException(e);
		}
	}
	
	public Object get(Class<?> clazz, Serializable id)
	{
		Object object = null;
		try
		{
			object = getSession().get(clazz, id);
		}
		catch (HibernateException e)
		{
			logger.error("HibernateSessionFactory get");
			throw new HibernateException(e);
		}
		finally
		{
			closeSession();
		}
		return object;
	}
}
